<?php

/**
 * mForge Framework
 *
 * LICENSE:
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * The license is bundled with this package in the file LICENSE.txt.
 * You may also obtain a copy of the License at this URL:
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @copyright  Copyright (c) 2011, Jonathan Hedrén
 * @author     Jonathan Hedrén <jonathan.hedren@gmail.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

namespace mForge;

class ViewResult implements IRoutingResult
{
    /**
     *
     * @var array
     */
    private $data;

    /**
     *
     * @var string
     */
    private $moduleName;

    /**
     *
     * @var string
     */
    private $viewName;

    /**
     *
     * @var string
     */
    private $layoutName;

    /**
     *
     * @param array $data
     * @param string $viewName
     * @param string $layoutName
     */
    public function __construct(array $data = array(), $viewName = null, $layoutName = 'default')
    {
        $this->data = $data;
        $this->viewName = $viewName;
        $this->layoutName = $layoutName;
    }

    /**
     * Does the actual inclusion of any view or layout file. Sets up the
     * key-value-pairs in $this->data as variables in the scope.
     * Returns the contents of the parsed file.
     *
     * @param string $__file__
     * @return string
     */
    private function doParse($__file__)
    {
        if (!is_file($__file__)) {
            throw new \Exception('No template file found @ ' . $__file__, 404);
        }

        foreach ($this->data as $var => $value) {
            ${$var} = $value;
        }

        ob_start();
        include($__file__);
        $output = ob_get_contents();
        ob_end_clean();

        return $output;
    }

    /**
     * 
     * @param Request $request
     * @param Response $response
     * @param Application $app 
     */
    public function executeResult(Request $request, Response $response, Application $app)
    {
       if ($this->viewName === null || $this->viewName === '') {
            $this->viewName = implode(DIRECTORY_SEPARATOR, $app->getRoutingContext()->getRouteTokens());
        }
        
        $this->render(
            $app->getAppPath(),
            $app->getBasePath(),
            $this->moduleName === null ? $app->getRoutingContext()->getModuleName() : $this->moduleName
        );
        $response->setBody($this->getContent());
        $response->send();
    }

    /**
     *
     * @param string $appPath
     * @param string $basePath
     * @param string $moduleName
     * @return ViewActionResult 
     */
    private function render($appPath, $basePath, $moduleName)
    {
        if (empty($moduleName)) {
            throw new \Exception('$moduleName is empty. Can\'t resolve a template file without the module name.');
        }

        // First try to load the template from the app directory
        $viewFile = $appPath . DIRECTORY_SEPARATOR
                  . 'views' . DIRECTORY_SEPARATOR
                  . 'templates' . DIRECTORY_SEPARATOR
                  . $moduleName . DIRECTORY_SEPARATOR
                  . $this->viewName . '.php';
        if (!is_file($viewFile)) {
            // try to load the template from the module directory
            $viewFile = $basePath . DIRECTORY_SEPARATOR
                      . 'modules' . DIRECTORY_SEPARATOR
                      . $moduleName . DIRECTORY_SEPARATOR
                      . 'views' . DIRECTORY_SEPARATOR
                      . 'templates' . DIRECTORY_SEPARATOR
                      . $this->viewName . '.php';
        }

        $this->content = $this->doParse($viewFile);

        if ($this->layoutName !== null) {
            $layoutPath = $appPath . DIRECTORY_SEPARATOR
                        . 'views' . DIRECTORY_SEPARATOR
                        . 'layouts' . DIRECTORY_SEPARATOR
                        . $this->layoutName . '.php';
            $this->content = $this->doParse($layoutPath);
        }

        return $this;
    }

    /**
     * Returns the rendered content.
     *
     * @return string
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Sets the module name.
     *
     * @param string $moduleName
     * @return ViewResult
     */
    public function setModuleName($moduleName)
    {
        $this->moduleName = $moduleName;
        return $this;
    }

    /**
     * Sets the view name.
     *
     * @param string $viewName
     * @return ViewResult
     */
    public function setViewName($viewName)
    {
        $this->viewName = $viewName;
        return $this;
    }

}